package com.csdj.server.config;

import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author zyq
 * @Date 2022/12/13 8:44
 * @ClassName: JwtTokenUtil
 * @Description: jwt工具类
 * @Version 1.0
 */
@Component
public class JwtTokenUtil {

    //jwt 用于存放 用户名
    private static final String CLAIM_KEY_USERNAME="sub";
    //存放 jwt token的创建时间
    private static final String CLAIM_KEY_CREATED="created";
    //密钥
    @Value("${jwt.secret}")
    private String secret;
     //有效时间
    @Value("${jwt.expiration}")
    private Long expiration;


    // 1.生成 jwt token

    /**
     * 准备 Jwt token 消息体
     * @param userDetails
     * @return
     */
    public String generateToken(UserDetails userDetails){
        Map<String,Object> claims=new HashMap<>();
        //存放 用户名
        claims.put(CLAIM_KEY_USERNAME,userDetails.getUsername());
        //jwt token 创建时间
        claims.put(CLAIM_KEY_CREATED,new Date());

        return generateToken(claims);
    }

    /**
     * 生成 token
     * @param claims
     * @return
     */
    private String generateToken(Map<String, Object> claims) {

        return Jwts.builder()
                .setClaims(claims)
                //有效时间
                .setExpiration(generateExpirationDate())
                //签名 密钥
                .signWith(SignatureAlgorithm.HS512,secret)
                //生成
                .compact();
    }

    /**
     * token 的有效时间
     * @return
     */
    private Date generateExpirationDate() {

        return new Date(System.currentTimeMillis()+expiration*1000);
    }


    //2.解析 token 通过cliam 拿到消息载体

    /**
     * 解析 token 拿到 消息载体
     * @param token
     * @return
     */
    public Claims getTokenInfo(String token){
        Claims claims=null;

        try {
            claims=Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return claims;

    }

    /**
     *  根据 token 拿到 用户名信息
     * @param token
     * @return
     */
    public String getUserNameFormToken(String token){
        String username=null;
        try {
            Claims claims = getTokenInfo(token);
            username = claims.getSubject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return username;
    }

    /**
     * 根据token 获取 token的有效时间
     * @param token
     * @return
     */
    public Date getTokenExpirationDate(String token){
        Claims claims = getTokenInfo(token);
       return claims.getExpiration();
    }

    //3. 判断 token 是否有效

    /**
     * 判断 token 是否 过期
     * @param token
     * @return
     */
    private boolean isTokenExpired(String token){
        //Claims claims = getTokenInfo(token);
        Date tokenExpirationDate = getTokenExpirationDate(token);
        //根据 token有效 是否在 当前系统时间之前
        //before Date类中的
       return tokenExpirationDate.before(new Date());
    }

    //通过 token 判断是否过期 用户信息是否匹配

    /**
     * 验证 token 是否失效
     * @param token
     * @param userDetails
     * @return
     */
    public boolean validateToken(String token,UserDetails userDetails){

        String username = getUserNameFormToken(token);
      return   username.equals(userDetails.getUsername())
              &&!isTokenExpired(token);
    }

    /**
     * 判断 token 能否刷新
     * @return
     */
    public boolean isCanRefresh(String token){

        return !isTokenExpired(token);
    }

    /**
     * 刷新 token
     * @param token
     * @return
     */
    public String refreshToken(String token){
        Claims claims = getTokenInfo(token);
        claims.put(CLAIM_KEY_CREATED,new Date());
        return generateToken(claims);
    }









}
